#! /usr/bin/python#-*- coding: UTF-8 -*- 
from twisted.internet.protocol import Protocol
from twisted.internet.protocol import Factory
from twisted.internet.endpoints import TCP4ServerEndpoint
from twisted.internet import reactor
from twisted.internet.threads import deferToThread
import time
import datetime
import redis
import re 
import sys,os
import time
from collections import defaultdict
import base64


pool_redis= redis.ConnectionPool(host='localhost',port=6379,decode_responses=True)
mesg_redis=redis.Redis(connection_pool=pool_redis)

def log_write(data):#日志log存储
	with open('sys_log/import_analysis_log','a') as f:
		f.write(data)
		f.write('&&')
#自动加载command文件夹里面的所有command命令文档，存储为字典{厂家型号：命令函数（）}，
#例如{'vk':lambda device_id,kind,param,model:vk_command(device_id,kind,param,model)}
analysis={}
first_handle={}
def impfile(filename):
	filelist,*_ = os.walk(filename,topdown=True)
	*_,filenames = filelist

	for i in filenames:
		print(i)
		if i[-3:] == '.py' and i != '__init__.py':
			try:
				device_model=re.search(r'(?P<model>\w*)_',i).group('model')
				exc = 'from '+ filename+'.'+i[:-3] + ' import '+ '*'
				exec(exc,globals())
				print(i[:-3])
				# analysis[device_model]=lambda datas:eval(i[:-3])(datas)#本地可运行，服务器不可
				analysis[device_model]=i[:-3]
				first_handle[device_model]=device_model+'_first_handle(data,self)'
			except Exception as e:
				analysis_log=str([i,e,datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')])
				log_write(analysis_log)

#命令函数目录名
impfile('analysis')
print('analysis',analysis)
print('first_handle',first_handle)


port_and_model={10712:'gumi'}
# port_and_model={23333:'jt808'}


class Iot_Pro(Protocol):
		
	def __init__(self,tml_id,data_buffer,separate_package):
		self.tml_id=tml_id
		self.name=None
		self.data_buffer=data_buffer
		self.separate_package=separate_package


	def connectionMade(self):
		print("new connect:")
		# print('self.data_buffer',self.data_buffer)
		# print(vars(self))
		# print(vars(self.transport))
		# print(self.transport.logstr)
		param=mesg_redis.rpop('set_param')
		if param!=None:
			# print(param)
			param=eval(param)
			# print('self.tml_id',self.tml_id)
			# print('param[0]',param[0])
			if param[0] in self.tml_id:
				if len(param)==3:
					self.tml_id[param[0]+'time_limit']=param[2]
					param=param[0:2]
				self.set_param(param)
			else:
				self.transport.write(b'mission fail!')

	def connectionLost(self, reason):

		client_num=str(self.transport.client)
		if client_num in self.tml_id:
			print('lost connected...:',self.tml_id[client_num])
			del self.tml_id[self.tml_id[client_num]]
			del self.tml_id[client_num]
		if client_num in self.data_buffer:
			del self.data_buffer[client_num]

	def dataReceived(self,origin_data):#接收数据，并进行初步处理

		protocol_num=self.transport.socket.getsockname()[1]
		print('data_receive---------')
		print('org_data',origin_data)
		data=origin_data
		first_result=eval(first_handle[port_and_model[protocol_num]])
		# print('first_result',first_result)

		if first_result!='0':
			
			buffer_id=self.transport.client
			# print('buffer_id',buffer_id)
			# print('self.data_buffer',self.data_buffer)
			self.data_buffer[buffer_id]+=first_result[0]
			data=self.data_buffer[buffer_id]
			buffer_result=eval(first_handle[port_and_model[protocol_num]])
			# print('buffer_result-----',buffer_result)
			if buffer_result=='0':
				self.data_buffer[buffer_id]=b''

			elif len(self.data_buffer[buffer_id])>12800000:
				self.data_buffer[buffer_id]=b''
			else:
				self.data_buffer[buffer_id]=buffer_result[0]
			

	def handle_data(self, data):#对数据包进行业务处理
		protocol_num=self.transport.socket.getsockname()[1]
		# print(analysis[port_and_model[protocol_num]]+(datas))
		d_done=eval(analysis[port_and_model[protocol_num]]+'(data)')
		# print('d_done',d_done)
		print('data_handle-------')
		client_num=str(self.transport.client)

		if 'device_id' in d_done:
			self.tml_id[client_num]=d_done['device_id']
			self.tml_id[d_done['device_id']]=self
		else:
			d_done['device_id']=self.tml_id[client_num]

		d_done['protocol_num']=protocol_num
		d_done['serv_receive']=datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')

		response=d_done.pop('response')

		if 'separate_package' in d_done:
			if d_done['device_id'] in self.separate_package:
				self.separate_package[d_done['device_id']].update(d_done['separate_package'])
			else:
				self.separate_package[d_done['device_id']]=d_done['separate_package']

		elif 'end_separate' in d_done:
			self.separate_package[d_done['device_id']].update(d_done['end_separate'])
			sep_data_dict=self.separate_package[d_done['device_id']]
			all_set_data=''
			# print('sep_data_dict-------',sep_data_dict)
			# 收到的数据排序
			data_que=sorted(list(sep_data_dict.keys()))

			for x in data_que:
				all_set_data+=sep_data_dict[x]

			separate_kind=d_done['separate_kind']

			if separate_kind in ['tk_mesg','img_data']:
				tk_data=base64.b64encode(bytes.fromhex(all_set_data)).decode()
				d_done[separate_kind]=tk_data
				print('record_voice------------------------------------ok',data_que)
			# 缓存的语音清零
			self.separate_package[d_done['device_id']]={}
			# 放入redis
			mesg_redis.lpush('data',str(d_done))
			# 计算录音的时间，时间借宿发指令结束录音
			self.tml_id[d_done['device_id']+'time_limit']=self.tml_id[d_done['device_id']+'time_limit']-1
			if self.tml_id[d_done['device_id']+'time_limit']==0:
				stop_record=bytes.fromhex('67670B00020001')
				self.transport.write(stop_record)

		else:
			print('d_done',d_done)
			mesg_redis.lpush('data',str(d_done))

		print('serv_receive',d_done['serv_receive'])

		return response

	def write_response(self, result):#数据包的处理结果，并返回数据给客户端

		# print("data_resule_:",result)
		print("write_response-------:")
		if result!=b'0':
			self.transport.write(result)


	def set_param(self,param):
		print("set_param-------:")
		self.tml_id[param[0]].transport.write(param[1])
		self.transport.write(b'set_param,ok!')



class Iot_Fact(Factory):
	def __init__(self):
		self.tml_id = {}
		self.data_buffer = defaultdict(bytes)
		self.separate_package={}
	def buildProtocol(self, addr):
		return Iot_Pro(self.tml_id,self.data_buffer,self.separate_package)	

for port in port_and_model:
	reactor.listenTCP(port,Iot_Fact())	
reactor.run()


